=pod
      Trade Me API Wrapper
      Copyright (C) 2011 Trade Me
      Author Tim Wright http://www.trademe.co.nz

      This library is free software; you can redistribute it and/or
      modify it under the terms of the GNU Lesser General Public
      License as published by the Free Software Foundation; either
      version 2.1 of the License, or (at your option) any later version.

      This library is distributed in the hope that it will be useful,
      but WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      Lesser General Public License for more details.

      You should have received a copy of the GNU Lesser General Public
      License along with this library; if not, write to the Free Software
      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
=cut

package TradeMeApiWrapper;

use strict;
use fields qw(key secret token token_secret);
use Data::Dumper;
use LWP::UserAgent;
use HTTP::Request::Common;
use HTTP::Request::Common qw(GET POST DELETE);

use Net::OAuth;
use Net::OAuth::AccessTokenRequest;
use Net::OAuth::RequestTokenRequest;
use Net::OAuth::ProtectedResourceRequest;

use Net::OAuth::UserAuthResponse;

use Digest::HMAC_SHA1;

$Net::OAuth::PROTOCOL_VERSION = Net::OAuth::PROTOCOL_VERSION_1_0A;

sub new {
    my TradeMeApiWrapper $self = shift;

    unless (ref $self) {
        $self = fields::new($self);
    }    
  
    $self->{'key'} = shift;
    $self->{'secret'} = shift;
    
    return $self;
}

sub get {
	my ($self, $url) = @_;

    my $ua  = LWP::UserAgent->new;
    
    my $request = Net::OAuth::ProtectedResourceRequest->new(
            consumer_key => $self->{'key'},
            consumer_secret => $self->{'secret'},
            request_url => $url,
            request_method => 'GET',
            signature_method => 'HMAC-SHA1',
            timestamp => time,
            nonce => nonce(),
			token => $self->{'token'},
			token_secret => $self->{'token_secret'}
    );
    
    $request->sign;

    die "Signature verification failed" unless $request->verify;
	
	my $response = $ua->request(GET $request->to_url);
	
	if ($response->is_success) {
        return $response->content;
    } else {
        die $response->status_line;
    }   
}

sub post {
	my ($self, $url, $xml) = @_;

    my $ua  = LWP::UserAgent->new;
    
    my $request = Net::OAuth::ProtectedResourceRequest->new(
            consumer_key => $self->{'key'},
            consumer_secret => $self->{'secret'},
            request_url => $url,
            request_method => 'POST',
            signature_method => 'HMAC-SHA1',
            timestamp => time,
            nonce => nonce(),
			token => $self->{'token'},
			token_secret => $self->{'token_secret'}
    );

    $request->sign;
    
	die "Signature verification failed" unless $request->verify;
	 
    my $response = $ua->request(POST $request->to_url,
    				Content_Type => 'text/xml',
     				Content => $xml);
     				
    if ($response->is_success) {
        return $response->content;
    } else {
        die $response->status_line;
    }     				
}

sub delete {
	my ($self, $url, $xml) = @_;

    my $ua  = LWP::UserAgent->new;
    
    my $request = Net::OAuth::ProtectedResourceRequest->new(
            consumer_key => $self->{'key'},
            consumer_secret => $self->{'secret'},
            request_url => $url,
            request_method => 'DELETE',
            signature_method => 'HMAC-SHA1',
            timestamp => time,
            nonce => nonce(),
			token => $self->{'token'},
			token_secret => $self->{'token_secret'}
    );

    $request->sign;	
	
    die "Signature verification failed" unless $request->verify;
    
    my $response = $ua->request(DELETE $request->to_url);
    if ($response->is_success) {
        return $response->content;
    } else {
        die $response->status_line;
    }
    
}

sub request_token {
	my ($self) = @_;
		
    my $ua  = LWP::UserAgent->new;	
    
    my $request = Net::OAuth::RequestTokenRequest->new(
    		callback => "oob",
            consumer_key => $self->{'key'},
            consumer_secret => $self->{'secret'},
            request_url => "https://secure.trademe.co.nz/Oauth/RequestToken",
            request_method => 'GET',
            signature_method => 'HMAC-SHA1',
            timestamp => time,
            nonce => nonce(),
            extra_params => { scope => "MyTradeMeRead,MyTradeMeWrite,BiddingAndBuying" }
    );

    $request->sign;	
	
	my $oauth_token; 
	my $oauth_secret;
	my $url = $ua->request(GET $request->to_url)->content;
	
	if ( $url =~ m/^oauth_token=(.*)&oauth_token_secret=(.*)&oauth_callback_confirmed=(.*)$/ ) {
    	return ($1, $2);    	
    }
	
	return ($oauth_token, $oauth_secret);	
}

sub access_token {
	my ($self, $token, $secret, $verifier) = @_;
			
    my $ua  = LWP::UserAgent->new;
    
    my $request = Net::OAuth::AccessTokenRequest->new(    
            consumer_key => $self->{'key'},
            consumer_secret => $self->{'secret'},
            request_url => "https://secure.trademe.co.nz/Oauth/AccessToken",
            request_method => 'GET',
            signature_method => 'HMAC-SHA1',
            timestamp => time,
            nonce => nonce(),
            token => $token,
            token_secret => $secret,
            verifier => $verifier
    );
    
    $request->sign;
	
	my $oauth_token; 
	my $oauth_secret;	
	my $url = $ua->request(GET $request->to_url)->content;
	
	if ( $url =~ m/^oauth_token=(.*)&oauth_token_secret=(.*)$/ ) {
    	$self->{'token'} = $oauth_token = $1;
    	$self->{'token_secret'} = $oauth_secret = $2;  	
    }
	
	return ($oauth_token, $oauth_secret);
}

sub request_verifier {
	my ($self, $oauth_token) = @_;
	system(( 'start', "https://secure.trademe.co.nz/Oauth/Authorize?oauth_token=$oauth_token" ));
}

sub nonce {
  my @chars = ('A'..'Z', 'a'..'z', 0..9);
  return join('', map($chars[rand(scalar(@chars))], 0..5));
}

1;